package cn.tedu.charging.order.service;

import cn.tedu.charging.common.constant.AmqpComponentConst;
import cn.tedu.charging.common.constant.MqttDestinationConst;
import cn.tedu.charging.common.pojo.message.ChargingStartCheckMessage;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.param.OrderAddParam;
import cn.tedu.charging.common.pojo.vo.VehicleVO;
import cn.tedu.charging.common.protocol.JsonResult;
import cn.tedu.charging.common.utils.CronUtil;
import cn.tedu.charging.common.utils.SnowflakeIdGenerator;
import cn.tedu.charging.order.amqp.AmqpProducer;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.mqtt.MqttProducer;
import cn.tedu.charging.order.utils.XxlJobTaskUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.UUID;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService{
    //注入一个服务调用客户端 设备
    @Autowired
    private DeviceClient deviceClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private MqttProducer<ChargingStartCheckMessage> mqttProducer;
    @Autowired
    private AmqpProducer<DelayCheckMessage> amqpProducer;
    private SnowflakeIdGenerator idGenerator
            =new SnowflakeIdGenerator(5,22);
    @Override
    public String createOrder(OrderAddParam param) {
        //1.根据入参参数 检查枪状态
        checkGun(param.getGunId());
        //2.查询车辆车主绑定信息
        VehicleVO vehicle=checkAndGetVehicle(param.getUserId());
        //3.生成本次扫码下单的订单编号
        String billId= generatorBillId();
        //4.发送生产消息给设备开始自检
        ChargingStartCheckMessage msg=new ChargingStartCheckMessage();
        msg.setOrderNo(billId);
        msg.setUserId(param.getUserId());
        msg.setGunId(param.getGunId());
        mqttProducer.sendAtLeastOnceStored(MqttDestinationConst.START_GUN_CHECK_PREFIX +param.getPileId(),msg);
        //5.订单给设备发送检测命令,准备延迟逻辑 检查最终设备自检结果
        DelayCheckMessage delayCheckMessage=new DelayCheckMessage();
        delayCheckMessage.setOrderNo(billId);
        delayCheckMessage.setUserId(param.getUserId());
        delayCheckMessage.setPileId(param.getPileId());
        delayCheckMessage.setGunId(param.getGunId());
        delayCheckMessage.setVehicleId(vehicle.getId());
        amqpProducer.send(delayCheckMessage, AmqpComponentConst.DELAY_BILL_EX);
        //6.组织一个定时计划任务,防止订单长时间未冲完,无法结束
        //6.1 模拟计划时间 2分钟
        String expression = CronUtil.delayCron(1000 * 60 * 2);//生成cron表达式 时间是2分钟之后
        log.debug("延迟时间:{}",expression);
        //6.2 发起一个http请求 创建定时任务
        XxlJobTaskUtil.createJobTask(new RestTemplate(),expression,2,billId);
        //7.正常扫码结束,修改枪状态
        deviceClient.updateGunStatus(param.getGunId(),2);
        return billId;
    }

    private String generatorBillId() {
        return idGenerator.nextId()+"";
    }

    private VehicleVO checkAndGetVehicle(Integer userId) {
        JsonResult<VehicleVO> result = userClient.bindedVehicle(userId);
        VehicleVO vo = result.getData();
        log.debug("查询车辆信息结果：{}",vo);
        if (vo==null){
            log.error("用户未绑定车辆");
            throw new RuntimeException("用户未绑定车辆");
        }else{
            return vo;
        }
    }

    private void checkGun(Integer gunId) {
        JsonResult<Boolean> result = deviceClient.checkGun(gunId);
        Boolean data = result.getData();
        if (!data){
           throw new RuntimeException("此枪不可用");
        }
    }
}
